package com.winway.framework.config;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import com.winway.common.constant.HttpStatus;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * Sa-Token配置类
 */
@Slf4j
@Configuration
@ConfigurationProperties(prefix = "security.ignored")
@Data
public class SaTokenConfig implements WebMvcConfigurer {

    private List<String> urls;

    private final Environment environment;

    public SaTokenConfig(Environment environment) {
        this.environment = environment;
    }

    /**
     * 注册Sa-Token拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        boolean isDev = environment.acceptsProfiles(Profiles.of("dev", "test"));
        log.info("注册Sa-Token拦截器，当前环境: {}", isDev ? "开发/测试" : "生产");

        // 创建拦截器
        SaInterceptor interceptor = new SaInterceptor(handler -> {
            // 登录校验 - 拦截需要登录的路由，并排除登录接口等公开路径
            SaRouter.match("/**")
                    .notMatch(urls)
                    .notMatch("/test/index")
                    .check(r -> {
                        log.debug("检查登录状态: {}", SaHolder.getRequest().getRequestPath());
                        StpUtil.checkLogin();
                    });

            // 角色校验 - 管理员校验
            SaRouter.match("/admin/**")
                    .check(r -> {
                        log.debug("检查管理员角色: {}", SaHolder.getRequest().getRequestPath());
                        StpUtil.checkRole("admin");
                    });
        });

        // 注册拦截器并设置拦截路径
        registry.addInterceptor(interceptor).addPathPatterns("/**");
    }

    /**
     * Sa-Token过滤器
     */
    @Bean
    public SaServletFilter saServletFilter() {
        return new SaServletFilter()
                // 拦截路径
                .addInclude("/**")
                // 排除路径
                .addExclude(
                        "/favicon.ico",
                        "/doc.html/**",
                        "/webjars/**",
                        "/druid/**",
                        "/h2-console/**"
                )
                // 前置函数：在每次拦截到请求前执行
                .setBeforeAuth(obj -> {
                    // 设置跨域响应头
                    SaHolder.getResponse()
                            .setHeader("Access-Control-Allow-Origin", "*")
                            .setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
                            .setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With")
                            .setHeader("Access-Control-Max-Age", "3600");

                    // 如果是预检请求，直接返回成功
                    if ("OPTIONS".equalsIgnoreCase(SaHolder.getRequest().getMethod())) {
                        SaHolder.getResponse().setStatus(HttpStatus.SUCCESS);
                        log.debug("OPTIONS预检请求放行");
                    }
                });
    }

    /**
     * Sa-Token 整合 JWT (Simple 模式)
     */
    @Bean
    public StpLogic getStpLogicJwt() {
        // 使用JWT整合模式
        return new StpLogicJwtForSimple();
    }
}
